
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <cinttypes>
#include <filesystem>
#include <unistd.h>
#include <vector>
#include <cassert>
#include <iostream>
#include <sys/time.h>
// ffd_binpack_umap.cpp
#include <algorithm>
#include <iomanip>
#include <unordered_map>


namespace fs = std::filesystem;

constexpr int CAP = 1024;
/* ---------- Bin 结构：保存 <idx,val> 对 ------------ */
struct Bin {
    std::vector<std::pair<int, int>> items;  // {idx, val}
    int sum = 0;

    bool try_put(const std::pair<int, int>& it) {
        if (sum + it.second > CAP) return false;
        items.push_back(it);
        sum += it.second;
        return true;
    }
};

std::vector<Bin> first_fit_decreasing(std::vector<std::pair<int,int>> sorted_elems);


union Data64to8
{
	uint64_t in64;
	int8_t out8[8];
};

struct MatrixS8 {
    int8_t* data = nullptr;
    size_t H;
    size_t W;

    size_t numel() const {
        return H * W;
    }

    void alloc(size_t H, size_t W) {
        if (this->data) free(this->data);
        this->H = H;
        this->W = W;
        this->data = (int8_t*)malloc(H*W);
    }
};

struct MatrixS32 {
    int32_t* data = nullptr;
    size_t H;
    size_t W;

    size_t numel() const {
        return H * W;
    }

    void alloc(size_t H, size_t W) {
        if (this->data) free(this->data);
        this->H = H;
        this->W = W;
        this->data = (int32_t*)malloc(H*W*4);
    }
};

struct VectorUS32 {
    uint32_t* data = nullptr;
    size_t SIZE;


    size_t numel() const {
        return SIZE;
    }

    void alloc(size_t SIZE) {
        if (this->data) free(this->data);
        this->SIZE = SIZE;
        this->data = (uint32_t*)malloc(SIZE*4);
    }
};

struct Timer {
    bool running;
    int time;
    struct timeval start_time;
    Timer() {
        reset();
    }

    void reset() {
        running = false;
        time = 0;
    }

    void start() {
        assert(!running);
        running = true;
        gettimeofday(&start_time, NULL);
    }

    void stop() {
        assert(running);
        running = false;
        
        struct timeval end_time;
        gettimeofday(&end_time, NULL);
        int elapsed_us = (end_time.tv_sec - start_time.tv_sec) * 1000000 + (end_time.tv_usec - start_time.tv_usec);
        
        time += elapsed_us;
    }

    void print(const char* msg) {
        assert(!running);
        printf("[debug] time, %s: %4dus\n", msg, time);
    }
};

void check_folder(const char *folder_path);

template <typename T>
bool write_bin_file(const char *filename, T *buffer, size_t size);

template <typename T>
bool read_bin_file(const char *filename, T *buffer, size_t size);

template <typename T>
size_t read_bin_file(const char *filename, T *buffer);

template <typename T>
size_t readBinToVec(std::vector<T>& data, const char* filename);

template <typename T>
size_t readBinToVec(std::vector<T>& data, std::string filename);

template <typename T>
bool exportVecToBin(const std::vector<T>& data, const char* filename);

